package com.smartboot.plus.api;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.smartboot.plus.exception.ServiceException;
import tech.smartboot.feat.core.common.HeaderValue;
import tech.smartboot.feat.core.common.HttpStatus;
import tech.smartboot.feat.core.server.HttpResponse;

import java.io.IOException;
import java.io.Serializable;
import java.util.Optional;

public class R<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    private int code;
    private boolean success;
    private T data;
    private String msg;

    // 私有构造方法
    private R(IResultCode resultCode) {
        this(resultCode, null, resultCode.getMessage());
    }

    private R(IResultCode resultCode, String msg) {
        this(resultCode, null, msg);
    }

    private R(IResultCode resultCode, T data) {
        this(resultCode, data, resultCode.getMessage());
    }

    private R(IResultCode resultCode, T data, String msg) {
        this(resultCode.getCode(), data, msg);
    }

    private R(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.success = ResultCode.SUCCESS.getCode() == code;
    }

    // Getter 方法
    public int getCode() {
        return code;
    }

    public boolean isSuccess() {
        return success;
    }

    public T getData() {
        return data;
    }

    public String getMsg() {
        return msg;
    }

    // Setter 方法
    public void setCode(int code) {
        this.code = code;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public void setData(T data) {
        this.data = data;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    // toString 方法
    @Override
    public String toString() {
        return "R{" +
                "code=" + code +
                ", success=" + success +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }

    // 静态方法
    public static boolean isSuccess(R<?> result) {
        return Optional.ofNullable(result)
                .map(x -> x.getCode() == ResultCode.SUCCESS.getCode())
                .orElse(Boolean.FALSE);
    }

    public static boolean isNotSuccess(R<?> result) {
        return !isSuccess(result);
    }

    public static <T> R<T> data(T data) {
        return data(data, "操作成功");
    }

    public static <T> R<T> data(T data, String msg) {
        return data(HttpStatus.OK.value(), data, msg);
    }

    public static <T> R<T> data(int code, T data, String msg) {
        return new R<>(code, data, data == null ? "暂无承载数据" : msg);
    }

    public static <T> R<T> success(String msg) {
        return new R<>(ResultCode.SUCCESS, msg);
    }

    public static <T> R<T> success(IResultCode resultCode) {
        return new R<>(resultCode);
    }

    public static <T> R<T> success(IResultCode resultCode, String msg) {
        return new R<>(resultCode, msg);
    }

    public static <T> R<T> fail(String msg) {
        return new R<>(ResultCode.FAILURE, msg);
    }

    public static <T> R<T> fail(int code, String msg) {
        return new R<>(code, null, msg);
    }

    public static <T> R<T> fail(IResultCode resultCode) {
        return new R<>(resultCode);
    }

    public static <T> R<T> fail(IResultCode resultCode, String msg) {
        return new R<>(resultCode, msg);
    }

    public static <T> R<T> status(boolean flag) {
        return flag ? success("操作成功") : fail("操作失败");
    }

    public static <T> void failResponse(HttpResponse response, String errorMessage) {
        R<T> result = new R<>(ResultCode.FAILURE.getCode(), null, errorMessage != null ? errorMessage : "操作失败");
        writeResponse(response, result);
    }

    public static <T> void failResponse(HttpResponse response, IResultCode resultCode, String errorMessage) {
        R<T> result = new R<>(resultCode.getCode(), null, errorMessage != null ? errorMessage : resultCode.getMessage());
        writeResponse(response, result);
    }

    public static <T> void successResponse(HttpResponse response, T data, String msg) {
        R<T> result = new R<>(ResultCode.SUCCESS.getCode(), data, msg != null ? msg : "操作成功");
        writeResponse(response, result);
    }

    public static <T> void failResponse(HttpResponse response, IResultCode resultCode) {
        failResponse(response, resultCode, null);
    }

    public static <T> void successResponse(HttpResponse response, T data) {
        successResponse(response, data, null);
    }

    public static <T> void writeResponse(HttpResponse response, R<T> result) {
        try {
            response.setContentType(HeaderValue.ContentType.APPLICATION_JSON);
            response.write(JSON.toJSON(result).toString());
            //   response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    public static <T> void handleException(ServiceException e, HttpResponse response) {
        response.setContentType(HeaderValue.ContentType.APPLICATION_JSON);
        // 构造错误响应
        try {

            R<T> result = new R<>(e.getResultCode(), null, e.getMessage());
            response.write(JSONObject.toJSONString(result).toString());

        } catch (IOException ioException) {
            ioException.printStackTrace();
        } finally {
            response.close();
        }
    }


    public static <T> void handleException(Exception e, HttpResponse response) {
        // 设置响应状态码

        response.setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);
        response.setContentType(HeaderValue.ContentType.APPLICATION_JSON);
        // 构造错误响应
        try {

            //java.lang.RuntimeException: java.lang.RuntimeException: 账号密码错误
            R<T> result = new R<>(ResultCode.INTERNAL_SERVER_ERROR.getCode(), null, e.getMessage());
            response.write(JSONObject.toJSONString(result).toString());
            //   response.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } finally {
            response.close();
        }
    }

    public static <T> void handleException(String e, HttpResponse response) {

        response.setContentType(HeaderValue.ContentType.APPLICATION_JSON);
        // 构造错误响应
        try {
            R<T> result = new R<>(ResultCode.INTERNAL_SERVER_ERROR.getCode(), null, e);
            response.write(JSONObject.toJSONString(result).toString());
            //   response.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } finally {
            response.close();
        }
    }
}
